﻿using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Media.Imaging;
using System.Data.SqlClient;

/*=====================================================================
  This file is part of a Microsoft SQL Server Shared Source Application.
  Copyright (C) Microsoft Corporation.  All rights reserved.
 
THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
======================================================= */


namespace Microsoft.SqlCommunity.FaultRetry
{
    /// <summary>
    /// This is the main window of the application.  It is used to browse and edit information about products in the
    /// AdventureWorksLT2008 database.  This application provides a simple example of how to use the custom mirror .NET data provider
    /// in a WPF based application.
    /// </summary>
	public partial class ProductEditorWindow
	{
        //Dialog used to pick the principal/mirror pair of servers which hold the database to edit.
        private ConfigureDialog _configureDialogWindow;  
        //Dialog used to confirm that changes should be discarded.
        private SaveChangesDialog _saveChangesDialogWindow;
        //Which principal/mirror server pair has been used to load product information
        private ServerSet _loadedServers = null;  
        
        public ProductEditorWindow()
		{
			this.InitializeComponent();

            // Create the configuration dialog
            _configureDialogWindow = new ConfigureDialog();
            _configureDialogWindow.ServerListsChanged += new EventHandler<EventArgs>(DataAccess.Current.ServerListsChangedHandler);

            //Only force the dialog to be displayed if there are no servers selected.  Otherwise just use what we picked last time
            //we used the application.
            if (!_configureDialogWindow.AreServersSelected)
            {
                bool? dialogResult  = _configureDialogWindow.ShowDialog();
                if (!dialogResult.HasValue || dialogResult.Value == false)
                {
                    Application.Current.Shutdown();
                    Environment.Exit(-1);
                }
            }
            //Pull in the product categories and populate the tree view.
            LoadCategoryTreeView();

		}

        /// <summary>
        /// Initialize the tree view control with the hierarchical list of product categories.
        /// </summary>
        private void LoadCategoryTreeView()
        {
            try
            {
                //Get the set of product categories from the data access layer and data bind to the tree control.
                //TODO: Put this off in it's own thread with progress updates in case primary is down.
                CategoryTreeView.ItemsSource = DataAccess.Current.GetCategories();
                //Keep track of where we got the categories from.
                _loadedServers = _configureDialogWindow.CurrentServers;
            }
            //If we're having trouble filling the tree control report the error to the user
            //TODO: We should probably log the error for the administrator and display something simple for the user.
            catch (SqlException se)
            {
                HandleLoadException(se);
            }
            catch (InvalidOperationException ioe)
            {
                HandleLoadException(ioe);
            }
        }

        /// <summary>
        /// Display an error message for the user when problems arise during loading of the tree control with data.
        /// </summary>
        /// <param name="e">The exception that was raised.</param>
        private void HandleLoadException(Exception e)
        {
            ShowError(e.Message);
            //Show an empty tree as another indication that something is wrong.
            CategoryTreeView.ItemsSource = null;
            _loadedServers = null;
        }


        /// <summary>
        /// Invoked when the user clicks the save button
        /// </summary>
        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            ClearError();
            // Ask the data access layer to save any changes.
            try
            {
                DataAccess.Current.SaveChanges();
            }
            catch (SqlException se)
            {
                ShowError(se.Message);
            }
        }

        /// <summary>
        /// Invoked when the user clicks on the Configure button.
        /// </summary>
        private void ConfigureButton_Click(object sender, RoutedEventArgs e)
        {
            ClearError();
            // Create a new dialog (we can't reuse the old one), and make sure to set up the handler to get invoked 
            // if the history of selected servers is changed.
            _configureDialogWindow = new ConfigureDialog();
            _configureDialogWindow.ServerListsChanged += new EventHandler<EventArgs>(DataAccess.Current.ServerListsChangedHandler);

            if (_configureDialogWindow.ShowDialog() == true)
            {
                //If we've changed the name of either server we may need to save previous work, and 
                //we must load our data from the new database.
                if (_loadedServers != null && !_loadedServers.Equals(_configureDialogWindow.CurrentServers))
                {
                    if (DataAccess.Current.IsDataChanged())
                    {
                        {
                            _saveChangesDialogWindow = new SaveChangesDialog();
                            if (_saveChangesDialogWindow.ShowDialog() == true)
                            {
                                if (_saveChangesDialogWindow.DialogChangeDisposition == SaveChangesDialog.ChangesDisposition.Save)
                                {
                                    try
                                    {
                                        DataAccess.Current.SaveChanges();
                                    }
                                    catch (SqlException se)
                                    {
                                        ShowError(se.Message);
                                    }
                                }
                            }
                            else
                            {
                                //Backout change of servers
                                _configureDialogWindow.CurrentServers = _loadedServers;
                                _configureDialogWindow.MaybeUpdateServerLists();
                                return;
                            }
                        }
                    }
                }
                // Refresh the tree view of product categories from the currently selected server pair.
                LoadCategoryTreeView();
            }
            else
            {
                if (_configureDialogWindow.DatabaseException != null)
                {
                    ShowError(_configureDialogWindow.DatabaseException);
                }
                //If the user didn't click on OK in the dialog and we don't have currently selected
                //principal/mirror server pair selected, then empty out the tree.
                if (_configureDialogWindow.CurrentServers == null) CategoryTreeView.ItemsSource = null;
            }

            _configureDialogWindow = null;
        }

        /// <summary>
        /// Invoked when the user clicks on the Exit button.  Used to cleanly terminate the application.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ExitButton_Click(object sender, RoutedEventArgs e)
        {
            //TODO: Check for unsaved changes
            Application.Current.Shutdown();
        }

        /// <summary>
        /// Invoke when the user clicks on a leaf product category.  Causes the product editor pane to fill with products from 
        /// the selected product category.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CategoryTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            ClearError();
            ProductCategory newCategory = e.NewValue as ProductCategory;
            if (newCategory != null)
            {
                //TODO: Check for unsaved changes
                try
                {
                    DataListView.DataContext = DataAccess.Current.GetProducts(newCategory);
                }
                catch (SqlException se)
                {
                    ShowError(se.Message);
                }
            }
        }

        /// <summary>
        /// Displays a message to the user, typically an error message.
        /// </summary>
        /// <param name="message">What message to display</param>
        private void ShowError(string message)
        {
            MessageTextBlock.Text = message;
            MessageScrollViewer.Visibility = Visibility.Visible;
        }

        /// <summary>
        /// Invoked in several places to clear off any error message which might be present.
        /// </summary>
        private void ClearError()
        {
            MessageScrollViewer.Visibility = Visibility.Hidden;
            MessageTextBlock.Text = string.Empty;
        }

        /// <summary>
        /// Invoked when the user clicks on the Clear button.  Throws away any changes, reset the connection
        /// to the database, and reloads the tree view.
        /// </summary>
        private void ClearButton_Click(object sender, RoutedEventArgs e)
        {
            ClearError();
            //TODO: Check if unsaved changes and offer to save
            try
            {
                DataAccess.Current.ResetConnection();
                LoadCategoryTreeView();
            }
            catch (SqlException se)
            {
                ShowError(se.Message);
            }
        }

	}
}